package com.support.widget.crypt;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


/**y
 * 
 *    
 * 类名称：ThreeDesUtil  
 * 类描述：  3DES/128AES/256AES/MD5/BASE64的加密及解密
 * 创建人：zhenglei  
 * 创建时间：2014-2-26 下午2:23:53  
 * 修改人：  
 * 修改时间：2014-2-26 下午2:23:53  
 * 修改备注：  
 * @version 1.0.0  
 *
 */
public class CryptTool {
	/**
	 * 3DES加密
	 * */
	public static class ThreeDES{
		private static final String Algorithm = "DESede"; 
		//private static final String key  =  "ece3fe290144a2cb8ee400c5";
		private final static String iv = "01234567"; 
			
		/**
		 * 
		 * @author zhenglei   
		 * encryptThreeDESECB  加密方法,将所有异常向业务层抛出
		 * @param src   需要加密的数据
		 * @return	加密以后的数据
		 * @throws Exception  String  
		 * @exception    
		 * @since  1.0.0
		 */
		public static String encryptThreeDESECB(String key,String src) throws Exception{  
			
		    DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));  
		    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm);  
		    SecretKey securekey = keyFactory.generateSecret(dks);  
		      
		    Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");  
		    IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); 
		    cipher.init(Cipher.ENCRYPT_MODE, securekey,ips);  
		    //为保证将明文字符串转换为byte[]后和ios转换的结果一致，采用该方法进行转换
		    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
		    DataOutputStream outputstream = new DataOutputStream(baos); 
		    outputstream.writeChars(src);
	 	    byte[] contents = baos.toByteArray();  
	 	   
	 	    byte[] b=cipher.doFinal(contents); 
		    
	 	    //Base64 encoder=new Base64();    
		    return new String(Base64.encodeBase64(b)).replaceAll("\r", "").replaceAll("\n", "");
		}  
		  
		/**
		 * 
		 * @author zhenglei   
		 * decryptThreeDESECB 解密方法，异常抛向业务层 
		 * @param src   需要解密的密文字符串
		 * @return  String  解密以后的明文
		 * @throws Exception  String
		 * @exception    
		 * @since  1.0.0
		 */
		public static String decryptThreeDESECB(String key,String src) throws Exception  
		{  
		    //--通过base64,将字符串转成byte数组  
	//	    BASE64Decoder decoder = new BASE64Decoder();  
	//	    byte[] bytesrc = decoder.decodeBuffer(src);  
		    byte[] bytesrc=src.getBytes();  
	        //Base64 base64=new Base64();  
	        //bytesrc=base64.decode(bytesrc);  
		    bytesrc = Base64.decodeBase64(bytesrc);
		    
		    //--解密的key  
		    DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));  
		    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm);  
		    SecretKey securekey = keyFactory.generateSecret(dks);  
		      
		    //--Chipher对象解密  
		    Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");  
		    IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); 
		    cipher.init(Cipher.DECRYPT_MODE, securekey,ips);  
		    byte[] retByte = cipher.doFinal(bytesrc);  
		    //加密时，采用的是writeChars()，该方法默认的编码方式是UTF-16,因此在将解密后的byte[]转换为字符串时需要设置编码方式为UTF-16
		    return new String(retByte,"UTF-16");
	 	}
	}
		/**
		 * MD5编码
		 * */
	public static class MD5{
		/**
		 * 
		 * @author zhenglei   
		 * MD5 编码方法，异常抛向业务层 
		 * @param src 需要编码的字符串
		 * @throws Exception  String
		 * @exception    
		 * @since  1.0.0
		 */
		public static String toMd5(String src) throws Exception{ 
			String result = "";
			MessageDigest md = MessageDigest.getInstance("MD5"); 
			md.update(src.getBytes()); 
			byte b[] = md.digest(); 
		        for (int i=0; i < b.length; i++) {
		            result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
		        } 
	
			return result; 
			} 
	}
	/**
	 * Base64编码
	 * */
	public static class Base64{
		/**
		 * 
		 * @author zhenglei   
		 * Base64 编码方法，异常抛向业务层 
		 * @param src 需要编码的字符串
		 * @throws Exception  String
		 * @exception    
		 * @since  1.0.0
		 */
		public static String encodeBase64(byte[] src) { 
			return new String(Base64.encodeBase64(src)).replaceAll("\r", "").replaceAll("\n", "");
			} 
		
		
		/**
		 * 
		 * @author zhenglei   
		 * Base64 解码方法，异常抛向业务层 
		 * @param bytesrc 需要解码的字符串
		 * @throws Exception  String
		 * @exception    
		 * @since  1.0.0
		 */
		public static byte[] decodeBase64(byte[] bytesrc) { 
			return Base64.decodeBase64(bytesrc);
			} 
		
	}
	/**
	 * AES 128位密钥加密
	 * */
	public static class AES128{
	
	/**
	 * 
	 * @author zhenglei   
	 * AES加密方法，异常抛向业务层 
	 * @param toEnc 需要加密的字符串
	 * @param key 密钥
	 * @throws Exception  String
	 * @exception    
	 * @since  1.0.0
	 */
	public static byte[] AESeEncrypt(byte[] toEnc, byte[] key) throws Exception {
	      // 秘密密钥
	      SecretKeySpec k = new SecretKeySpec(key, "AES");
	      // 生成 Cipher对象
	      Cipher cipher = Cipher.getInstance("AES");
	      // 指定模式 、密钥
	      cipher.init(Cipher.ENCRYPT_MODE, k);
	      // 加密数据
	      return cipher.doFinal(toEnc);
	  }

	/**
	 * 
	 * @author zhenglei   
	 * AES解密方法，异常抛向业务层 
	 * @param toDec 需要解密的字符串
	 * @param key 密钥
	 * @throws Exception  String
	 * @exception    
	 * @since  1.0.0
	 */
	  public static byte[] AESDecrypt(byte[] toDec, byte[] key) throws Exception {
	      // 秘密密钥
	      SecretKeySpec k = new SecretKeySpec(key, "AES");
	      // 生成 Cipher对象
	      Cipher cipher = Cipher.getInstance("AES");
	      // 指定模式 、密钥
	      cipher.init(Cipher.DECRYPT_MODE, k);
	      // 解密数据
	      return cipher.doFinal(toDec);
	  }

		/**
		 * 
		 * @author zhenglei   
		 * 产生密钥
		 * @throws Exception  String
		 * @exception    
		 * @since  1.0.0
		 */
	  public static byte[] genKey() throws Exception {
	    try {
	      KeyGenerator gen = KeyGenerator.getInstance("AES");
	      SecureRandom rdm = SecureRandom.getInstance("SHA1PRNG");
	      rdm.setSeed(seedKey().getBytes());
	      gen.init(128, rdm);
	      return gen.generateKey().getEncoded();
	    }
	    catch (NoSuchAlgorithmException e) {
	      throw new Exception(e);
	    }
	  }

		/**
		 * 
		 * @author zhenglei   
		 * 产生密钥种子
		 * @throws Exception  String
		 * @exception    
		 * @since  1.0.0
		 */
	  private static String seedKey() {
	    String rdmCode = "";
	    int rdmInt = (int)((new Random()).nextFloat() * 100);
	    if (0 < rdmInt) {
	      if (rdmInt < 10) {
	        rdmCode = "0" + rdmInt;
	      }
	      else {
	        rdmCode = "" + rdmInt;
	      }
	    }
	    return System.currentTimeMillis() + rdmCode;
	  }

	  /**
	   * 原文的字符编码
	   */
	  private static String charset = "utf-8";
	  public static void setCharset(String charset) {
	    AES128.charset = charset;
	  }

	  public static String getCharset() {
	    return charset;
	  }
	}
}